#include <iostream>

#include <xlitecore/csobject.h>
#include <xlitecore/cslinkedlist.h>
#include <windows.h>
#include <string>
CS_USE_NAMESPACE(CS_NAMESPACE)

class csLiteObjectTest : public csObject
{
	CS_OBJECT(csLiteObjectTest)
public:
	explicit csLiteObjectTest(csObject* pParent = nullptr)
		: csObject(pParent)
	{
		CS_REG_METHOD(csLiteObjectTest, test, CS_NOT_CONST);
		CS_REG_ARG1METHOD(csLiteObjectTest, testArg, int, CS_NOT_CONST);
		CS_REG_ARG2METHOD(csLiteObjectTest, testArg, int, double, CS_NOT_CONST);
		CS_REG_ARG3METHOD(csLiteObjectTest, testArg, int, double, float, CS_NOT_CONST);
		CS_REG_ARG4METHOD(csLiteObjectTest, testArg, int, double, float, bool, CS_NOT_CONST);
		CS_REG_ARG5METHOD(csLiteObjectTest, testArg, int, double, float, bool, char, CS_NOT_CONST);

		CS_REG_RETURN_METHOD(csLiteObjectTest, testRet, int, CS_NOT_CONST);
		CS_REG_RETURN_ARG1METHOD(csLiteObjectTest, testArgRet, int, int, CS_NOT_CONST);
		CS_REG_RETURN_ARG2METHOD(csLiteObjectTest, testArgRet, int, int, double, CS_NOT_CONST);
		CS_REG_RETURN_ARG3METHOD(csLiteObjectTest, testArgRet, int, int, double, float, CS_NOT_CONST);
		CS_REG_RETURN_ARG4METHOD(csLiteObjectTest, testArgRet, int, int, double, float, bool, CS_NOT_CONST);
		CS_REG_RETURN_ARG5METHOD(csLiteObjectTest, testArgRet, int, int, double, float, bool, char, CS_NOT_CONST);

		//CS_REG_PROPERTY(csLiteObjectTest, testValue, const int&, getTestValue, int, setTestValue);
		CS_REG_PROPERTY(csLiteObjectTest, id, int, id, const int&, setId);
		CS_REG_READONLY_PROPERTY(csLiteObjectTest, age, int, age);
		CS_REG_WRITEONLY_PROPERTY(csLiteObjectTest, age, int, setAge);
	}
	void test()
	{
		std::cout << __FUNCTION__ << std::endl;
	}
	void testArg(int v1)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << std::endl;
	}
	void testArg(int v1, double v2)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << std::endl;
	}
	void testArg(int v1, double v2, float v3)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << std::endl;
	}
	void testArg(int v1, double v2, float v3, bool v4)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << " v4 = " << v4 << std::endl;
	}
	void testArg(int v1, double v2, float v3, bool v4, char v5)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << " v4 = " << v4 << " v5 = " << v5 << std::endl;
	}
	int testRet()
	{
		std::cout << __FUNCTION__ << std::endl;
		return 0;
	}
	int testArgRet(int v1)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << std::endl;
		return 1;
	}
	int testArgRet(int v1, double v2)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << std::endl;
		return 2;
	}
	int testArgRet(int v1, double v2, float v3)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << std::endl;
		return 3;
	}
	int testArgRet(int v1, double v2, float v3, bool v4)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << " v4 = " << v4 << std::endl;
		return 4;
	}
	int testArgRet(int v1, double v2, float v3, bool v4, char v5)
	{
		std::cout << __FUNCTION__ << " v1 = " << v1 << " v2 = " << v2 << " v3 = " << v3 << " v4 = " << v4 << " v5 = " << v5 << std::endl;
		return 5;
	}
	const int& getTestValue() const
	{
		return m_testValue;
	}
	void setTestValue(int testValue)
	{
		m_testValue = testValue;
	}
	int id() const
	{
		return m_testId;
	}
	void setId(const int& id)
	{
		m_testId = id;
	}
	int age() const
	{
		return m_age;
	}
	void setAge(int age)
	{
		m_age = age;
	}
private:
	int m_testValue;
	int m_testId;
	int m_age;
};

void methodTest()
{
	csObject obj;
	obj.invoke("test");
	std::string s;
	obj.invoke("hello", CS_ARG(std::string&, s));
	std::cout << obj.parent() << std::endl;

	csLiteObjectTest testObj;
	csObject* pObj = &testObj;
	int value = 0;
	testObj.setTestValue(100);
	pObj->invoke("getTestValue", CS_RETURN_ARG(int, value));
	std::cout << value << std::endl;
	value = 111;
	pObj->invoke("setTestValue", CS_ARG(int, value));
	int val2 = 0;
	pObj->invoke("getTestValue", CS_RETURN_ARG(int, val2));
	std::cout << val2 << std::endl;
	pObj->invoke("test");
	pObj->invoke("testArg", CS_ARG(int, 400));
	pObj->invoke("testArg", CS_ARG(int, 20), CS_ARG(double, 90.0));
	pObj->invoke("testArg", CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f));
	pObj->invoke("testArg", CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f), CS_ARG(bool, true));
	pObj->invoke("testArg", CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f), CS_ARG(bool, true), CS_ARG(char, 'A'));

	int ret = -1;
	pObj->invoke("testRet", CS_RETURN_ARG(int, ret));
	std::cout << "ret test : " << ret << std::endl;
	pObj->invoke("testArgRet", CS_RETURN_ARG(int, ret), CS_ARG(int, 400));
	std::cout << "ret test : " << ret << std::endl;
	pObj->invoke("testArgRet", CS_RETURN_ARG(int, ret), CS_ARG(int, 20), CS_ARG(double, 90.0));
	std::cout << "ret test : " << ret << std::endl;
	pObj->invoke("testArgRet", CS_RETURN_ARG(int, ret), CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f));
	std::cout << "ret test : " << ret << std::endl;
	pObj->invoke("testArgRet", CS_RETURN_ARG(int, ret), CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f), CS_ARG(bool, true));
	std::cout << "ret test : " << ret << std::endl;
	pObj->invoke("testArgRet", CS_RETURN_ARG(int, ret), CS_ARG(int, 20), CS_ARG(double, 90.0), CS_ARG(float, 40.0f), CS_ARG(bool, true), CS_ARG(char, 'A'));
	std::cout << "ret test : " << ret << std::endl;
}

void propertyTest()
{
	csVariant variant = csVariant::fromValue('4');
	variant.setValue(100);
	std::cout << variant.value<int>() << " " << variant.toInt() << std::endl;
	csLiteObjectTest lot;
	lot.setProperty("id", csVariant::fromValue(100));
	std::cout << lot.property("id").value<int>() << std::endl;

	csVariant bValue = false;
	std::cout << bValue.value<bool>() << std::endl;
	std::cout << (bValue.toBool() == 0) << std::endl;
}

void linkedListTest()
{
	csLinkedList<int> list;
	for (int i = 0; i < 100; i++)
	{
		list.insert(i, 0);
	}
	csLinkedList<int>::iterator it = list.begin();
	*it = 200;
	for (auto value : list)
	{
		std::cout << "value : " << value << std::endl;
	}

	for (auto cit = list.cbegin(); cit != list.cend(); cit++)
	{
		std::cout << "value : " << *cit << std::endl;
	}

	const csLinkedList<int>& clist = list;
	for (auto value : clist)
	{
		std::cout << "value : " << value << std::endl;
	}
}

int main(int argc, char* argv[])
{
	methodTest();
	//propertyTest();
	//linkedListTest();
	return 0;
}
